#include "BondFuture.h"
#include "bondlib/Pinyin.h"

CBondExpireFuture::CBondExpireFuture()
{
}

void CBondExpireFuture::GetFutureMap(CBondExpireData& data)
{
	SCOPED_MUTEX(m_mutex);
	data = m_ExpireData;
}

bool CBondExpireFuture::InsertFutureMap(xQBTFAllContractInfoAck_c* pAck)
{
	if (!pAck) return false;
	SCOPED_MUTEX(m_mutex);
	bool bReturn = false;
	for (std::list<xQBTFAllContractInfo_c>::const_iterator itr = pAck->m_List.begin();
		itr != pAck->m_List.end(); itr++){
		if (m_ExpireData.m_mapExpire.find(itr->m_TF_ID) == m_ExpireData.m_mapExpire.end()){
			bReturn = true;
			m_ExpireData.m_mapExpire.insert(std::make_pair(itr->m_TF_ID, *itr));
		}
	}
	return bReturn;
}

CBondFuture& CBondFuture::instance()
{
	static	CBondFuture	g_bondfuture;
	return g_bondfuture;
}

CBondFuture::CBondFuture() : m_unNatChangeDate(0)
{
}

CBondFuture::~CBondFuture()
{
	Clear( );
}

void CBondFuture::SetChangeDate(unsigned int date)
{
	SCOPED_MUTEX(m_mutex);
	m_unNatChangeDate = date;
}

unsigned int CBondFuture::GetChangeDate()
{
	SCOPED_MUTEX(m_mutex);
	return m_unNatChangeDate;
}

bool CBondFuture::Clear()
{
	m_future.m_data.clear();
	return true;
}

int CBondFuture::Add(CFutureInfo &element)
{
	if (GetFutureInfo(element.m_TF_ID,NULL)){
		SCOPED_MUTEX(m_mutex);
		std::vector<CFutureInfo>::iterator itr = m_future.m_data.begin();
		while (itr!=m_future.m_data.end()){
			if (std::string(itr->m_TF_ID) == std::string(element.m_TF_ID)){
				*itr = element;
				break;
			}
			itr++;
		}
		return -1;
	}

	FIELDCOPY(element.m_sPinyin, qb::PinyinManager::instance().GetPinyin(element.m_InstrumentName).c_str());
	m_future.m_data.push_back(element);
	int nIndex = m_future.m_data.size()-1;
	return nIndex;
}

bool CBondFuture::Load(CStDatabase * pDB, void *cookie)
{
	SCOPED_MUTEX(m_mutex);
	//SP_ASSERT( pDB );
	Clear();
	//pDB->LoadFuturetable(*this);
	return true;
}

int CBondFuture::GetSize() 
{ 
	return m_future.m_data.size(); 
}

bool CBondFuture::GetFutureInfo(const char *szCode, CFutureInfo *pInfo)
{
	SCOPED_MUTEX(m_mutex);
	if (nullptr==szCode || strlen(szCode)<=0)
		return false;

	std::vector<CFutureInfo>::iterator itr = m_future.m_data.begin();
	while (itr!=m_future.m_data.end()){
		if (std::string(itr->m_TF_ID) == std::string(szCode)){
			if(pInfo){
				*pInfo = *itr;
			}
			return true;
		}
		itr++;
	}
	return false;
}

bool CBondFuture::GetFutureInfoByKey(const char * szKey, CFutureInfo * pInfo)
{
	SCOPED_MUTEX(m_mutex);
	if (nullptr==szKey || strlen(szKey)<=0)
		return false;

	std::vector<CFutureInfo>::iterator itr = m_future.m_data.begin();
	while (itr!=m_future.m_data.end()){
		if (std::string(itr->m_TF_Key) == std::string(szKey)){
			if (pInfo){
				*pInfo = *itr;
			}
			return true;
		}
		itr++;
	}
	return false;
}

CFutureArray& CBondFuture::GetFutureArray()
{
	return m_future;
}

const CFutureArray& CBondFuture::GetFutureArray()const
{
	return m_future;
}

void CBondFuture::GetFutureArray(CFutureArray& futureArray)
{
	SCOPED_MUTEX(m_mutex);
	futureArray.m_data.clear();
	if (m_future.m_data.size() > 0){
		futureArray.m_data = m_future.m_data;
	}
}

CFutureRefBond& CFutureRefBond::instance()
{
	static CFutureRefBond bond;
	return bond;
}

CFutureRefBond::CFutureRefBond()
{
}

CFutureRefBond::~CFutureRefBond()
{
}

void CFutureRefBond::Clear()
{
	SCOPED_MUTEX(m_mutex);
	m_mpRefBond.clear();
}

bool CFutureRefBond::Add(const xQBRefBond_c& refBond)
{
	CFutureInfo fi;
	if(!CBondFuture::instance().GetFutureInfoByKey(refBond.m_TF_Key, &fi))
		return false;

	CFutureRefInfo rfInfo;
	FIELDCOPY(rfInfo.m_TF_ID,fi.GetFutureCode());
	FIELDCOPY(rfInfo.m_bondKey,refBond.m_Bond_Key);
	rfInfo.m_convertFactor = refBond.m_Conversion_Factor;
	
	std::string strTFID = fi.GetFutureCode();

	SCOPED_MUTEX(m_mutex);
	std::map<std::string, CFutureRefList>::iterator it = m_mpRefBond.find(strTFID);
	if(it == m_mpRefBond.end())
	{
		CFutureRefList lst;
		lst.m_data.push_back(rfInfo);
		m_mpRefBond[strTFID] = lst;
	}
	else
	{
		CFutureRefList& lst = m_mpRefBond[strTFID];
		std::list<CFutureRefInfo>::iterator itl = lst.m_data.begin();
		for(; itl!=lst.m_data.end(); itl++)
		{
			if(strcmp(rfInfo.m_bondKey, itl->m_bondKey)==0)
				return false;
		}
		lst.m_data.push_back(rfInfo);
	}
	return true;
}

CFutureRefList CFutureRefBond::GetRefBondList(const char* tfId)
{
	SCOPED_MUTEX(m_mutex);
	CFutureRefList rst;
	if(m_mpRefBond.find(tfId) != m_mpRefBond.end())
		rst = m_mpRefBond[tfId];
	return rst;
}

bool CFutureRefBond::GetRefBondConvertFactor(const char* tfId, const char* bondKey, double& dFactor)
{
	SCOPED_MUTEX(m_mutex);
	if(m_mpRefBond.find(tfId) != m_mpRefBond.end())
	{
		CFutureRefList& rst = m_mpRefBond[tfId];
		std::list<CFutureRefInfo>::iterator it = rst.m_data.begin();
		for(; it!=rst.m_data.end(); it++)
		{
			if(strcmp(it->m_bondKey, bondKey)==0)
			{
				dFactor = it->m_convertFactor;
				return true;
			}
		}
	}
	return false;
}

CFutureRefListEx CFutureRefBond::GetAllTFRefBondList()
{
	SCOPED_MUTEX(m_mutex);
	CFutureRefListEx ret;
	std::map<std::string, CFutureRefList>::iterator it = m_mpRefBond.begin();
	for(; it!=m_mpRefBond.end(); it++)
	{
		std::string strCode = it->first;
		if(strCode.size()!=6 || strCode.find("TF")!=0) continue;

		CFutureRefList& lst = it->second;
		for(auto rit=lst.m_data.begin(); rit!=lst.m_data.end(); rit++)
		{
			std::string strBondKey = rit->m_bondKey;
			if(find(ret.m_data.begin(), ret.m_data.end(), strBondKey) == ret.m_data.end())
				ret.m_data.push_back(strBondKey);
		}
	}
	return ret;
}

CFutureRefListEx CFutureRefBond::GetAllTRefBondList()
{
	SCOPED_MUTEX(m_mutex);
	CFutureRefListEx ret;
	std::map<std::string, CFutureRefList>::iterator it = m_mpRefBond.begin();
	for(; it!=m_mpRefBond.end(); it++)
	{
		std::string strCode = it->first;
		if(strCode.size()!=5 || strCode.find("T")!=0) continue;

		CFutureRefList& lst = it->second;
		for(auto rit=lst.m_data.begin(); rit!=lst.m_data.end(); rit++)
		{
			std::string strBondKey = rit->m_bondKey;
			if(find(ret.m_data.begin(), ret.m_data.end(), strBondKey) == ret.m_data.end())
				ret.m_data.push_back(strBondKey);
		}
	}
	return ret;
}

CFutureRefListEx CFutureRefBond::GetAllTSRefBondList() {
	SCOPED_MUTEX(m_mutex);
	CFutureRefListEx ret;
	std::map<std::string, CFutureRefList>::iterator it = m_mpRefBond.begin();
	for (; it != m_mpRefBond.end(); it++)
	{
		std::string strCode = it->first;
		if (strCode.size() != 6 || strCode.find("TS") != 0) continue;

		CFutureRefList& lst = it->second;
		for (auto rit = lst.m_data.begin(); rit != lst.m_data.end(); rit++)
		{
			std::string strBondKey = rit->m_bondKey;
			if (find(ret.m_data.begin(), ret.m_data.end(), strBondKey) == ret.m_data.end())
				ret.m_data.push_back(strBondKey);
		}
	}
	return ret;
}

void CActiveFinBond::Clear()
{
	SCOPED_MUTEX(m_mutex);
    m_data.m_List.clear();
}

bool CActiveFinBond::Add(const xQBDealActiveFinancialBondUnit_t& activeFinBond)
{
    CActiveFinBondInfo activeInfo;
    FIELDCOPY(activeInfo.m_bondkey,activeFinBond.m_bondkey);
    FIELDCOPY(activeInfo.m_listedmarket,activeFinBond.m_listedmarket);
    activeInfo.m_nTransCount = activeFinBond.m_nTransCount;

	SCOPED_MUTEX(m_mutex);
    std::list<CActiveFinBondInfo>::iterator it = m_data.m_List.begin();
    for (; it!=m_data.m_List.end(); ++it){
        if ((strcmp(activeInfo.m_bondkey, it->m_bondkey)==0) &&
			(strcmp(activeInfo.m_listedmarket, it->m_listedmarket)==0))
            return false;
    }
    m_data.m_List.push_back(activeInfo);
    return true;
}

CActiveFinBondList CActiveFinBond::GetActiveFindBondList()
{
    //调用不加锁
	SCOPED_MUTEX(m_mutex);
    CActiveFinBondList rst;
    rst = m_data;
    return rst;
}

void CActiveFinBond::Sort()
{
	SCOPED_MUTEX(m_mutex);
    m_data.m_List.sort();
}

bool CActiveFinBond::IsActiveFinancialBond(CBondInfo& bi)
{
	SCOPED_MUTEX(m_mutex);
    auto it = m_data.m_List.begin();
    for (; it!=m_data.m_List.end(); ++it){
        if ((strcmp(bi.GetBondKey(), it->m_bondkey)==0) &&
			(strcmp(bi.GetListedMarket(), it->m_listedmarket)==0))
            return true;
    }
    return false;
}

